﻿using CommunicationLib.Base;
using CommunicationLib.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace CommunicationLib
{
    public class Communication : CommunicationBase
    {
        private IPAddress ipAddress = null;
        private int netPort = 0;
        private string comName = "COM1";
        private int comBaudRate = 9600;
        private CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

        public event Action<object, CommunicationArgsBase> OnError;
        public event Action<object, DataPackage> OnReceived;
        /// <summary>
        /// 网口通讯录模式初始化
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="netPort"></param>
        public void Initialize(IPAddress ipAddress, int netPort)
        {
            this.ipAddress = ipAddress;
            this.netPort = netPort;
            CommunicationMode = Enums.CommunicationMode.TCP;
            tcpClient = new System.Net.Sockets.TcpClient();
            Init();
        }
        /// <summary>
        /// 串口通讯模式初始化
        /// </summary>
        public void Initialize(string comName, int comBaudRate)
        {
            this.comName = comName;
            this.comBaudRate = comBaudRate;
            CommunicationMode = Enums.CommunicationMode.SerialPort;
            serialPort = new System.IO.Ports.SerialPort(comName, comBaudRate);
            Init();

        }
        /// <summary>
        ///   内部初始化
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void Init()
        {
            //初始化PLC特有的参数
          
        }


        public override void Send(DataPackage dataPackage)
        {
            this.Package = dataPackage;
            switch (CommunicationMode)
            {
                case Enums.CommunicationMode.TCP:
                    if (tcpClient != null && tcpClient.Connected)
                    {

                        try
                        {
                            tcpClient.Client.Send(dataPackage.SendBuffer);//发送数据
                        }
                        catch (Exception ex)
                        {
                           
                            OnError?.Invoke(this, new CommunicationArgsBase() { Message = "发送tcp数据发生错误", Exception = ex });
                           
                        }
                    }
                    break;
                  
                case Enums.CommunicationMode.SerialPort:
                    if (serialPort != null && serialPort.IsOpen)
                    {
                        try
                        {
                            serialPort.Write(dataPackage.SendBuffer, 0, dataPackage.SendBuffer.Length);//发送数据
                        }
                        catch (Exception ex)
                        {
                            OnError?.Invoke(this, new CommunicationArgsBase() { Message = "发送串口数据发生错误", Exception = ex });
                        }
                        break;
                    }
                    break;
            }
        }

        public override bool Start()
        {
            switch (CommunicationMode)
            {
                case Enums.CommunicationMode.TCP:
                    try
                    {
                        Task.Factory.StartNew(Receive);//接收tcp数据
                        return true;
                    }
                    catch (Exception ex)
                    {
                        OnError?.Invoke(this, new CommunicationArgsBase() { Message = "接收tcp数据发生错误", Exception = ex });

                        return false;
                    }

                case Enums.CommunicationMode.SerialPort:
                    if (serialPort == null)
                    {
                        OnError?.Invoke(this, new CommunicationArgsBase() { Message = "serial没有初始化" });

                    }
                    try
                    {
                        if (serialPort.IsOpen == false)
                        {
                            serialPort.Open();
                        }
                        serialPort.DataReceived -= SerialPort_DataReceived;//接收串口数据
                        serialPort.DataReceived += SerialPort_DataReceived;//接收串口数据
                        return true;
                    }
                    catch (Exception ex)
                    {
                        OnError?.Invoke(this, new CommunicationArgsBase() { Message = "打开串口发生错误", Exception = ex });
                        return false;
                    }

            }
            return false;
        }
        /// <summary>
        ///    接收串口数据的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void SerialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            Task.Run(() =>
            {
                try
                {
                    int count = serialPort.BytesToRead;// 获取串口缓冲区中的字节数
                    byte[] buffer = new byte[count];// 创建一个缓冲区来存储读取的数据
                    serialPort.Read(buffer, 0, count); // 从串口读取数据
                    byte[] receiveBuffer = buffer.Take(count).ToArray(); // 只取实际接收到的字节数
                    lock (lockRingBuffer)
                    {
                        if (RingBuffer == null)
                        {
                            RingBuffer = new RingBufferManager(65535); // 初始化环形缓冲区
                        }
                        RingBuffer.WriteBuffer(buffer); // 写入数据到环形缓冲区
                    }
                    // 如果需要读取的长度未设置，则设置为环形缓冲区中的数据长度
                    if (Package.NeedLength == -1)
                    {
                        lock (lockRingBuffer)
                        {
                            receiveBuffer = new byte[receiveBuffer.Length];// 创建接收缓冲区
                            RingBuffer.ReadBuffer(receiveBuffer, 0, receiveBuffer.Length);// 从环形缓冲区读取数据包
                            RingBuffer.Clear(receiveBuffer.Length);// 清除已读取的数据
                            Package.ReceiveBuffer = receiveBuffer;
                            RingBuffer.ReceiveTime = DateTime.Now;
                            OnReceived?.Invoke(this, Package); // 触发数据接收事件
                        }
                    }
                    //从环形缓冲区读取数据包
                    if (RingBuffer.DataCount >= Package.NeedLength && Package.NeedLength > 0)
                    {
                        lock (lockRingBuffer)
                        {
                            receiveBuffer = new byte[Package.NeedLength];// 创建接收缓冲区
                            RingBuffer.ReadBuffer(receiveBuffer, 0, Package.NeedLength); // 从环形缓冲区读取数据包
                            RingBuffer.Clear(receiveBuffer.Length);// 清除已读取的数据
                            Package.ReceiveBuffer = receiveBuffer;
                            RingBuffer.ReceiveTime = DateTime.Now;
                            OnReceived?.Invoke(this, Package); // 触发数据接收事件
                        }
                    }
                    //if (RingBuffer.DataCount  >= 0)
                    //{
                    //    lock (lockRingBuffer)
                    //    {
                    //        byte[] receiveBuffer = new byte[RingBuffer.DataCount];
                    //        RingBuffer.ReadBuffer(receiveBuffer, 0, receiveBuffer.Length); // 从环形缓冲区读取数据包
                    //        RingBuffer.Clear(receiveBuffer.Length);// 清除已读取的数据
                    //        Package.ReceiveBuffer = receiveBuffer;
                    //        RingBuffer.ReceiveTime = DateTime.Now;
                    //        OnReceived?.Invoke(this, Package); // 触发数据接收事件
                    //    }
                    //}
                }
                catch (Exception ex)
                {
                    tcpClient.Client.Shutdown(SocketShutdown.Both);// 关闭连接
                    Thread.Sleep(10); // 等待10毫秒后
                    tcpClient.Client.Close(); // 关闭连接
                    OnError?.Invoke(this, new CommunicationArgsBase() { Message = "接收串口数据发生错误", Exception = ex });

                }
            });
        }
        /// <summary>
        /// 
        /// </summary>
        private void Receive()
        {
            while (!CancellationTokenSource.Token.IsCancellationRequested)// 循环接收数据，直到取消请求
            {
                try
                {
                    if (tcpClient == null || tcpClient.Connected == false)
                    {
                        Thread.Sleep(1000);
                        continue;
                    }
                    int count = tcpClient.Available; // 获取可用数据的字节数
                    byte[] buffer = new byte[count];
                    count = tcpClient.Client.Receive(buffer); // 此处阻塞，直到接收到数据
                    byte[] receiveBuffer = buffer.Take(count).ToArray(); // 只取实际接收到的字节数
                    if (receiveBuffer.Length > 0)
                    {
                        lock (lockRingBuffer)
                        {
                            if (RingBuffer == null)
                            {
                                RingBuffer = new RingBufferManager(65535); // 初始化环形缓冲区
                            }
                            RingBuffer.WriteBuffer(buffer); // 写入数据到环形缓冲区
                        }
                        if (Package.NeedLength == -1)
                        {
                            // 如果需要读取的长度未设置，则设置为环形缓冲区中的数据长度
                            lock (lockRingBuffer)
                            {
                                receiveBuffer = new byte[receiveBuffer.Length];
                                RingBuffer.ReadBuffer(receiveBuffer, 0, receiveBuffer.Length); // 从环形缓冲区读取数据包
                                RingBuffer.Clear(receiveBuffer.Length);// 清除已读取的数据
                                Package.ReceiveBuffer = receiveBuffer;
                                RingBuffer.ReceiveTime = DateTime.Now;
                                OnReceived?.Invoke(this, Package); // 触发数据接收事件
                            }
                        }
                        //从环形缓冲区读取数据包
                     else if (RingBuffer.DataCount >= Package.NeedLength && Package.NeedLength > 0)
                        {
                            lock (lockRingBuffer)
                            {
                                receiveBuffer = new byte[Package.NeedLength];
                                RingBuffer.ReadBuffer(receiveBuffer, 0, Package.NeedLength); // 从环形缓冲区读取数据包
                                RingBuffer.Clear(receiveBuffer.Length);// 清除已读取的数据
                                Package.ReceiveBuffer = receiveBuffer;
                                RingBuffer.ReceiveTime = DateTime.Now;
                                OnReceived?.Invoke(this, Package); // 触发数据接收事件
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    tcpClient.Client.Shutdown(SocketShutdown.Both);// 关闭连接
                    Thread.Sleep(1000); // 等待1秒钟后
                    tcpClient.Client.Close(); // 关闭连接
                    OnError?.Invoke(this, new CommunicationArgsBase() { Message = "接收tcp数据发生错误", Exception = ex });
                }
            }
        }
        //接收tcp数据的回调子线程
        public override bool Stop()
        {
            CancellationTokenSource.Cancel(); // 取消接收数据的任务
            throw new NotImplementedException();
        }

        public ConnectionResult Connect(bool reConnect = false)
        {
            ConnectionResult connectionResult = new ConnectionResult();

            switch (CommunicationMode)
            {
                case Enums.CommunicationMode.TCP:
                    try
                    {
                        // 如果是重新连接，先断开连接
                        if (reConnect)
                        {
                            tcpClient = new TcpClient();
                        }
                        tcpClient.Connect(ipAddress, netPort);// 连接到tcp服务器
                        connectionResult.Message = "连接成功";
                        connectionResult.Success = true;
                    }
                    catch (Exception ex)
                    {
                        connectionResult.Exception = ex;
                    }
                    break;

                case Enums.CommunicationMode.SerialPort:
                    if (serialPort == null)
                    {
                        serialPort = new System.IO.Ports.SerialPort(comName, comBaudRate);
                    }
                    try
                    {
                        serialPort.Open(); // 打开串口
                        connectionResult.Message = "连接成功";
                        connectionResult.Success = true;
                    }
                    catch (Exception ex)
                    {
                        connectionResult.Exception = ex;
                        connectionResult.Message = "连接失败";
                        connectionResult.Success = false;
                    }
                    break;
                // 其他通讯模式可以在这里添加
                default:
                    break;
            }
            return connectionResult;
        }

        public ConnectionResult ShakeHands(byte[] finsBytes, int maxMilliseconds = 3000)// 握手方法
        {
            ConnectionResult connectionResult = new ConnectionResult();
            switch (CommunicationMode)
            {
                case Enums.CommunicationMode.TCP:
                    try
                    {
                        if (tcpClient == null || tcpClient.Connected == false)
                        {
                            connectionResult.Message = "未连接到服务器";
                            connectionResult.Success = false;
                            return connectionResult;
                        }
                        
                        Stopwatch stopwatch = Stopwatch.StartNew();// 启动计时器
                        var stream = tcpClient.GetStream();// 获取网络流
                        
                        // 修复：使用同步方法避免异步问题
                        stream.Write(finsBytes, 0, finsBytes.Length); // 发送握手指令
                        Thread.Sleep(1);
                        stream.Flush(); // 确保数据发送完成
                        
                        // 等待响应
                        while (stopwatch.ElapsedMilliseconds < maxMilliseconds)
                        {
                            if (tcpClient.Available > 0)
                            {
                                break;
                            }
                            Thread.Sleep(10);
                        }
                        
                        if (tcpClient.Available > 0)
                        {
                            byte[] receiveBuffer = new byte[tcpClient.Available];// 创建接收缓冲区
                            int bytesRead = stream.Read(receiveBuffer, 0, receiveBuffer.Length); // 从网络流中读取数据
                            
                            // 只取实际读取的字节
                            byte[] actualReceived = new byte[bytesRead];
                            Array.Copy(receiveBuffer, actualReceived, bytesRead);
                            
                            stopwatch.Stop(); // 停止计时器
                            connectionResult.Success = true;
                            connectionResult.Content = actualReceived; // 将接收到的数据存储在Content中
                            connectionResult.Message = $"握手成功，接收到{bytesRead}字节";
                        }
                        else
                        {
                            connectionResult.Success = false;
                            connectionResult.Message = "握手超时，未收到响应";
                        }
                    }
                    catch (Exception ex)
                    {
                        connectionResult.Exception = ex;
                        connectionResult.Message = "发送握手指令失败";
                        connectionResult.Success = false;
                    }
                    break;
                case Enums.CommunicationMode.SerialPort:
                    // 串口握手逻辑（如果需要）
                    break;
            }
            return connectionResult;
        }
    }
}
